package com.study_security.logging;

import com.study_security.domain.LoginUser;
import com.study_security.dto.UserDTO;
import com.study_security.entity.SysLog;
import com.study_security.mapper.UserMapper;
import com.study_security.service.SysLogService;
import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import java.time.LocalDateTime;
import java.util.Arrays;

@Aspect
@Component
public class LogAspect {

    @Autowired
    private SysLogService sysLogService;

    @Autowired
    UserMapper userMapper;

    @Around("execution(* com.study_security.controller.*.*(..))") // 目标切点
    public Object logControllerMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        // 记录方法开始时间
        long startTime = System.currentTimeMillis();

        // 获取请求信息
        String methodName = joinPoint.getSignature().getName();   // 方法名
        String className = joinPoint.getTarget().getClass().getName(); // 类名
        String params = Arrays.toString(joinPoint.getArgs());    // 请求参数

        // 获取 HttpServletRequest
        HttpServletRequest request = getCurrentHttpRequest();

        // 获取 HTTP 方法
        String httpMethod = request != null ? request.getMethod() : "UNKNOWN";

        // 记录用户信息（这里假设通过 SecurityContextHolder 获取用户）
        Long userId = getCurrentUserId();  // 需要你自己实现获取当前用户ID的方法

        String status = "SUCCESS";

        // 执行目标方法
        Object result = null;
        try {
            result = joinPoint.proceed();
            return result;
        } catch (Throwable throwable){
            status = "FAILURE";
            throw throwable; // 重新抛出异常，以便上层处理
        } finally{
            // 计算响应时间
            long endTime = System.currentTimeMillis();
            long responseTime = endTime - startTime;

            // 构建日志对象
            SysLog sysLog = new SysLog();
            if (userId != null) {
                sysLog.setUserId(userId);
                UserDTO userDTO = userMapper.selectUserInfoById(userId);
                sysLog.setUserName(userDTO.getUserName());
            } else {
                sysLog.setUserId(-1L); // 表示未认证用户
            }
            sysLog.setOperationType(httpMethod);
            sysLog.setRequestUrl(className + "." + methodName);  // 用方法名来标识请求
            sysLog.setMethod(methodName);
            sysLog.setParams(params);
            sysLog.setResponseTime(responseTime);
            sysLog.setStatus(status);
            sysLog.setCreatedAt(LocalDateTime.now());

            // 保存日志
            sysLogService.save(sysLog);
        }
    }
    private Long getCurrentUserId() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        // 检查用户是否已登录
        if (authentication != null && authentication.isAuthenticated()) {
            Object principal = authentication.getPrincipal();
            if (principal instanceof LoginUser) {
                return ((LoginUser) principal).getUser().getId(); // 获取用户ID
            }
        }

        // 如果没有认证信息，则返回null或抛出异常
        return null; // 或者你可以选择抛出一个异常，具体根据需求
    }
    private HttpServletRequest getCurrentHttpRequest() {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if(requestAttributes != null){
            return (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
        }
        return null;
    }
}

